package org.proxywars.engine.test;

import com.jme.animation.SpatialTransformer;
import com.jme.bounding.BoundingSphere;
import com.jme.light.PointLight;
import com.jme.math.FastMath;
import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.scene.Controller;
import com.jme.scene.shape.Box;
import com.jme.scene.state.BlendState;
import com.jme.scene.state.CullState;
import com.jme.scene.state.LightState;
import com.jme.scene.state.MaterialState;
import com.jme.scene.state.BlendState.DestinationFunction;
import com.jme.scene.state.BlendState.SourceFunction;
import com.jme.scene.state.CullState.Face;
import com.jme.system.DisplaySystem;
import com.jmex.game.state.BasicGameState;

/**
 * This GameStates simply displays a few rotating Boxes.
 * A Light and LightState is creates to illuminate the Scene.
 * A BlendState is created to make use of transparent Materials.
 * Then a few Boxes with a SpatialTransformer, to move them around are attached to the rootNode.
 * 
 * -- Just a rename of Core-Dump's ThreeDeGameState
 */
public class BoxGameState extends BasicGameState {
    public BoxGameState(String name) {
        super(name);
        // shortcut reference
        Renderer renderer = DisplaySystem.getDisplaySystem().getRenderer();
        
        // make sure the rootNode is rendered in the Transparent Queue
        rootNode.setRenderQueueMode(Renderer.QUEUE_TRANSPARENT);
        
        // Add a light to the Scene
        PointLight light = new PointLight();
        light.setDiffuse( new ColorRGBA( 0.75f, 0.75f, 0.75f, 1f ) );
        light.setAmbient( new ColorRGBA( 0.5f, 0.5f, 0.5f, 1f ) );
        light.setLocation( new Vector3f( 0, 2, 0 ) );
        light.setEnabled( true );
        LightState lightState = renderer.createLightState();
        lightState.setEnabled( true );
        lightState.attach(light);
        rootNode.setRenderState(lightState);
 
        // we need to cull the backfaces, or Transparent objects will look wrong
        CullState cs = renderer.createCullState();
        cs.setCullFace(Face.Back);
        rootNode.setRenderState(cs);

        // The BlendState is needed to make the Boxes appear transparent
        BlendState bs = renderer.createBlendState();
        bs.setBlendEnabled(true);
        bs.setSourceFunction(SourceFunction.SourceAlpha);
        bs.setDestinationFunction(DestinationFunction.OneMinusSourceColor);
        rootNode.setRenderState(bs);
        
        // create 5 colorful and spinning boxes
        for (int i = 0; i < 5; i++) {
            Box b = new Box("b", new Vector3f(-1,-1,-1), new Vector3f(1, 1, 1));
            b.setModelBound(new BoundingSphere());
            b.updateModelBound();
            
            MaterialState ms = renderer.createMaterialState();
            b.setRenderState(ms);
            ms.setAmbient(new ColorRGBA(FastMath.rand.nextFloat(),FastMath.rand.nextFloat(),FastMath.rand.nextFloat(),0.5f));
            ms.setDiffuse(new ColorRGBA(FastMath.rand.nextFloat(),FastMath.rand.nextFloat(),FastMath.rand.nextFloat(),0.5f));
            ms.setSpecular(ColorRGBA.white.clone());
            ms.setShininess(128);
            b.setRenderState(ms);
            
            // Add a spatial Transformer to let the Boxes Spin wildly
            SpatialTransformer trans = new SpatialTransformer(1);
 
            Quaternion x0 = new Quaternion();
            x0.fromAngleAxis(0, Vector3f.UNIT_Y);
            Quaternion x180 = new Quaternion();
            x180.fromAngleAxis(FastMath.DEG_TO_RAD*180, Vector3f.UNIT_Y);
            Quaternion x360 = new Quaternion();
            x360.fromAngleAxis(FastMath.DEG_TO_RAD*360, Vector3f.UNIT_Y);
            trans.setRotation(0, 0, x0);
            trans.setRotation(0, 5, x180);
            trans.setRotation(0, 10, x360);
            trans.setObject(b, 0, 0);
            trans.interpolateMissing();
            trans.setRepeatType(Controller.RT_WRAP);
            trans.setPosition(0, 0, new Vector3f(i, i, i));
            trans.setPosition(0, 5, new Vector3f(i, FastMath.rand.nextFloat()*-2, i));
            trans.setPosition(0, 10, new Vector3f(i, i, i));
            b.addController(trans);
            
            // attach the Box to the root Node
            rootNode.attachChild(b);
        }

        rootNode.updateRenderState();
        rootNode.updateGeometricState(0, true);
    }
}

